package org.mybatis.generator.api.plus;

import java.util.*;

import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;

/** @author wangfupeng */
public class MybatisPluginController extends PluginAdapter {

    private FullyQualifiedJavaType slf4jLogger;
    private FullyQualifiedJavaType slf4jLoggerFactory;
    private FullyQualifiedJavaType autowired;
    private FullyQualifiedJavaType mediaType;
    private FullyQualifiedJavaType pathVariable;
    private FullyQualifiedJavaType requestBody;
    private FullyQualifiedJavaType requestHeader;
    private FullyQualifiedJavaType requestMapping;
    private FullyQualifiedJavaType postMapping;
    private FullyQualifiedJavaType getMapping;
    private FullyQualifiedJavaType requestMethod;
    private FullyQualifiedJavaType requestParam;
    private FullyQualifiedJavaType restController;
    private FullyQualifiedJavaType checkLimit;
    private FullyQualifiedJavaType authUser;
    private FullyQualifiedJavaType logging;
    private FullyQualifiedJavaType listResponse;
    private FullyQualifiedJavaType simpleResponse;
    private FullyQualifiedJavaType api;
    private FullyQualifiedJavaType apiOperation;
    private FullyQualifiedJavaType apiParam;

    private FullyQualifiedJavaType controllerType;

    private FullyQualifiedJavaType serviceType;
    private FullyQualifiedJavaType distinctServiceType;
    private FullyQualifiedJavaType modelType;
    private FullyQualifiedJavaType modelExampleType;
    private FullyQualifiedJavaType javaUtilListType;


    private String basePackage;
    private String aspectPackage;
    private String servicePackage;
    private String controllerPackage;
    private String project;
    private String modelUrl;
    private String enableGenerateHtml;
    private String htmlPath;


    private FullyQualifiedJavaType stringType;
    private FullyQualifiedJavaType integerType;
    private FullyQualifiedJavaType booleanType;
    private FullyQualifiedJavaType byteType;
    private FullyQualifiedJavaType doubleType;
    private FullyQualifiedJavaType floatType;
    private FullyQualifiedJavaType longType;
    private FullyQualifiedJavaType shortType;
    private FullyQualifiedJavaType bigDecimalType;
    private FullyQualifiedJavaType dateType;

    /**
     * 所有的方法
     */
    private List<Method> methods;

    /**
     * 是否添加注解
     */

    public MybatisPluginController() {
        super();
        methods = new ArrayList<Method>();
        // default is slf4j
        slf4jLogger = new FullyQualifiedJavaType("org.slf4j.Logger");
        slf4jLoggerFactory = new FullyQualifiedJavaType("org.slf4j.LoggerFactory");
        autowired = new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired");
        mediaType = new FullyQualifiedJavaType("org.springframework.http.MediaType");
        pathVariable = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.PathVariable");
        requestBody = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestBody");
        requestMapping = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestMapping");
        postMapping = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.PostMapping");
        getMapping = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.GetMapping");
        requestMethod = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestMethod");
        requestParam = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestParam");
        requestHeader = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RequestHeader");
        restController = new FullyQualifiedJavaType("org.springframework.web.bind.annotation.RestController");
        api = new FullyQualifiedJavaType("io.swagger.annotations.Api");
        apiOperation = new FullyQualifiedJavaType("io.swagger.annotations.ApiOperation");
        apiParam = new FullyQualifiedJavaType("io.swagger.annotations.ApiParam");
        stringType = new FullyQualifiedJavaType("java.lang.String");
        integerType = new FullyQualifiedJavaType("java.lang.Integer");
        booleanType = new FullyQualifiedJavaType("java.lang.Boolean");
        byteType = new FullyQualifiedJavaType("java.lang.Byte");
        doubleType = new FullyQualifiedJavaType("java.lang.Double");
        floatType = new FullyQualifiedJavaType("java.lang.Float");
        longType = new FullyQualifiedJavaType("java.lang.Long");
        shortType = new FullyQualifiedJavaType("java.lang.Short");
        bigDecimalType = new FullyQualifiedJavaType("java.lang.BigDecimal");
        dateType = new FullyQualifiedJavaType("java.util.Date");

    }

    /**
     * 读取配置文件
     */
    @Override
    public boolean validate(List<String> warnings) {
        this.modelUrl = context.getJavaModelGeneratorConfiguration().getTargetPackage();
        this.basePackage = properties.getProperty("basePackage");
        this.servicePackage = properties.getProperty("servicePackage");
        this.project = properties.getProperty("targetProject");
        this.controllerPackage = properties.getProperty("controllerPackage");
        this.aspectPackage = properties.getProperty("aspectPackage");
        this.checkLimit = new FullyQualifiedJavaType(aspectPackage + ".CheckLimit");
        this.authUser = new FullyQualifiedJavaType(aspectPackage + ".AuthUser");
        this.logging = new FullyQualifiedJavaType(aspectPackage + ".Logging");
        this.enableGenerateHtml = properties.getProperty("enableGenerateHtml");
        this.htmlPath = properties.getProperty("htmlPath");
        this.simpleResponse = new FullyQualifiedJavaType(basePackage+".controller.response.SimpleResponse");
        this.listResponse = new FullyQualifiedJavaType(basePackage+".controller.response.ListResponse");
        return true;
    }

    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        List<GeneratedJavaFile> files = new ArrayList<>();
        String table = introspectedTable.getBaseRecordType();
        String tableName = table.replaceAll(this.modelUrl + ".", "");
        if(tableName.equals("Admin")){
            MybatisUtilLoginController.writeLoginController(basePackage,project,servicePackage);
        }
        serviceType = new FullyQualifiedJavaType(servicePackage + "." + tableName + "Service");
        distinctServiceType = new FullyQualifiedJavaType(servicePackage + ".distinct.Distinct" + tableName + "Service");
        modelType = new FullyQualifiedJavaType(modelUrl + "." + tableName);
        modelExampleType = new FullyQualifiedJavaType(modelUrl + "." + tableName + "Example");
        controllerType = new FullyQualifiedJavaType(controllerPackage + ".Common" + tableName + "Controller");
        TopLevelClass topLevelClass = new TopLevelClass(controllerType);
        addImport(topLevelClass);
        addLogger(topLevelClass);
        addService(topLevelClass, introspectedTable, tableName, files);
        return files;
    }

    /**
     * import must class 导入必要的class
     */
    private void addImport(TopLevelClass topLevelClass) {
        // addImportedType是往一个set里面加数据，所以可以重复添加。
        // 导入必须的类
        topLevelClass.addImportedType(slf4jLogger);
        topLevelClass.addImportedType(slf4jLoggerFactory);
        topLevelClass.addImportedType(autowired);
        topLevelClass.addImportedType(mediaType);
        topLevelClass.addImportedType(pathVariable);
        topLevelClass.addImportedType(requestBody);
        topLevelClass.addImportedType(requestHeader);
        topLevelClass.addImportedType(requestMapping);
        topLevelClass.addImportedType(getMapping);
        topLevelClass.addImportedType(postMapping);
        topLevelClass.addImportedType(requestMethod);
        topLevelClass.addImportedType(requestParam);
        topLevelClass.addImportedType(restController);
        topLevelClass.addImportedType(checkLimit);
        topLevelClass.addImportedType(authUser);
        topLevelClass.addImportedType(logging);
        topLevelClass.addImportedType(api);
        topLevelClass.addImportedType(apiOperation);
        topLevelClass.addImportedType(apiParam);
        topLevelClass.addImportedType(simpleResponse);
        topLevelClass.addImportedType(listResponse);
        topLevelClass.addImportedType(stringType);
        topLevelClass.addImportedType(integerType);
        topLevelClass.addImportedType(serviceType);
        topLevelClass.addImportedType(distinctServiceType);
        topLevelClass.addImportedType(modelType);
        topLevelClass.addImportedType(modelExampleType);
        topLevelClass.addImportedType(javaUtilListType);
        topLevelClass.addImportedType(controllerType);

    }

    /**
     * public static final Logger logger =
     * LoggerFactory.getLogger(UserLabelReturnFieldController.class);
     */
    private void addLogger(TopLevelClass topLevelClass) {
        Field field = new Field();
        field.setFinal(true);
        field.setInitializationString("LoggerFactory.getLogger(" + topLevelClass.getType().getShortName() + ".class)");
        field.setName("logger");
        field.setStatic(true);
        field.setType(new FullyQualifiedJavaType("Logger"));
        field.setVisibility(JavaVisibility.PUBLIC);
        topLevelClass.addField(field);
    }

    /**
     * add TopClass and All Method
     */
    protected void addService(TopLevelClass topLevelClass, IntrospectedTable introspectedTable, String tableName,
                              List<GeneratedJavaFile> files) {
        topLevelClass.setVisibility(JavaVisibility.PUBLIC);
        // set service
        topLevelClass.addAnnotation("@SuppressWarnings({\"unchecked\",\"rawtypes\"})");
        topLevelClass.addAnnotation("@Api(description = \"脚手架自动生成的通用的增删改查列表" + tableName + "接口\")");
        topLevelClass.addAnnotation("@RestController");
        topLevelClass.addAnnotation("@RequestMapping(value = \"/v1/common/" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(tableName)
                + "\", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)");
        topLevelClass.addSuperInterface(logging);
        /** add import mapper */
        addField(topLevelClass, tableName);
        /** add method */
        topLevelClass.addMethod(addModelMethod(introspectedTable, tableName));
        String pathForPrimaryKeyColumns = MybatisUtilCommon.getPathForPrimaryKeyColumns(introspectedTable);
        if(!"".equals(pathForPrimaryKeyColumns)) {
            topLevelClass.addMethod(deleteByPrimaryKeyMethod(introspectedTable, tableName));
            if(MybatisUtilCommon.getExistNonePrimaryKeyColumns(introspectedTable)) {
                topLevelClass.addMethod(updateMethod(introspectedTable, tableName));
                topLevelClass.addMethod(selectByPrimaryKeyMethod(introspectedTable, tableName));
                topLevelClass.addMethod(selectByPrimaryKeyMockMethod(introspectedTable, tableName));
            }
        }
        topLevelClass.addMethod(list(introspectedTable, tableName));
        topLevelClass.addMethod(listMockWithoutAuthUser(introspectedTable, tableName));
        topLevelClass.addMethod(listWithoutCache(introspectedTable, tableName));
        topLevelClass.addMethod(listWithMock(introspectedTable, tableName));
        topLevelClass.addMethod(query(introspectedTable, tableName));
        topLevelClass.addMethod(distinct(introspectedTable, tableName));
        GeneratedJavaFile file = new GeneratedJavaFile(topLevelClass, project, "UTF-8", context.getJavaFormatter());
        files.add(file);
    }

    /**
     * @Autowired private UserLabelReturnFieldMapper userLabelReturnFieldMapper;
     */
    protected void addField(TopLevelClass topLevelClass, String tableName) {
        Field field = new Field();
        field.setName(getServiceShort());
        field.setType(serviceType);
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Autowired");
        topLevelClass.addField(field);
        Field fieldDistinct = new Field();
        fieldDistinct.setName(MybatisUtilCommon.toLowerCaseAtFirstCharacter("Distinct"+serviceType.getShortName()));
        fieldDistinct.setType(distinctServiceType);
        fieldDistinct.setVisibility(JavaVisibility.PRIVATE);
        fieldDistinct.addAnnotation("@Autowired");
        topLevelClass.addField(fieldDistinct);
    }

    protected Method addModelMethod(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"增加" + tableName + "\")");
        method.addAnnotation("@PostMapping(value = \"/add\")");
        method.setReturnType(simpleResponse);
        method.setName("add");
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(modelType, MybatisUtilCommon.toLowerCaseAtFirstCharacter(tableName), "@RequestBody"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" + getServiceShort() + ".add(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(tableName) + "));");
        return method;
    }

    private String getServiceShort() {
        return MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName());
    }

    protected Method selectByPrimaryKeyMethod(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"查询" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/get" + MybatisUtilCommon.getPathForPrimaryKeyColumns(introspectedTable) + "\")");
        method.setName("get");
        method.setReturnType(simpleResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        MybatisUtilCommon.addParameterWithAnnotationForPrimaryKeyColumnsInMethodSelectByPrimaryKey(method, introspectedTable);
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" + getServiceShort() + ".getWithCache(" + MybatisUtilCommon.getParameterValueForPrimaryKeyColumns(introspectedTable) + "));");
        return method;
    }

    protected Method selectByPrimaryKeyMockMethod(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"查询" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/mock" + MybatisUtilCommon.getPathForPrimaryKeyColumns(introspectedTable) + "\")");
        method.setName("mock");
        method.setReturnType(simpleResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        MybatisUtilCommon.addParameterWithAnnotationForPrimaryKeyColumnsInMethodSelectByPrimaryKey(method, introspectedTable);
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" + getServiceShort() + ".getCacheMockThenFetchLater(" + MybatisUtilCommon.getParameterValueForPrimaryKeyColumns(introspectedTable) + "));");
        return method;
    }

    private Method updateMethod(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"更改" + tableName + "\")");
        method.addAnnotation("@PostMapping(value = \"/update\")");
        method.setName("update");
        method.setReturnType(simpleResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(modelType, MybatisUtilCommon.toLowerCaseAtFirstCharacter(tableName), "@RequestBody"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" + getServiceShort() + ".update(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(tableName) + "));");
        return method;
    }


    private Method deleteByPrimaryKeyMethod(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"删除" + tableName + ",传入id, 返回data : 成功 : 1, 失败 : 0\")");
        method.addAnnotation("@GetMapping(value = \"/delete"+ MybatisUtilCommon.getPathForPrimaryKeyColumns(introspectedTable)+"\")");
        method.setName("delete");
        method.setReturnType(simpleResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        MybatisUtilCommon.addParameterWithAnnotationForPrimaryKeyColumnsInMethodSelectByPrimaryKey(method, introspectedTable);
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" + getServiceShort() + ".delete("+MybatisUtilCommon.getParameterValueForPrimaryKeyColumns(introspectedTable)+"));");
        return method;
    }

    private Method listWithMock(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@CheckLimit");
        method.addAnnotation("@ApiOperation(\"查询缓存列表，返回缓存数据，然后去后台查询进缓存，后面再次查询返回缓存数据" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/listWithMock\")");
        method.setName("listWithMock");
        method.setReturnType(listResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(integerType, "page", "@ApiParam(value = \"" + tableName
                + " 页码\") @RequestParam(value = \"page\", required = false, defaultValue = \"1\") "));
        method.addParameter(new Parameter(integerType, "limit", "@ApiParam(value = \"" + tableName
                + " 一页返回条数\") @RequestParam(value = \"limit\", required = false, defaultValue = \"20\")"));
        method.addParameter(new Parameter(stringType, "orderBy", "@ApiParam(value = \"" + tableName
                + " 排序模式\") @RequestParam(value = \"orderBy\", required = false, defaultValue = \"id asc\")"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine(
                modelExampleType.getShortName() + " " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName())
                        + " = new " + modelExampleType.getShortName() + "();");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setLimit(limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOffset((page-1)*limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOrderByClause(orderBy);");
        method.addBodyLine("Integer count = Integer.valueOf(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".countByExampleCacheMockThenFetchLater(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ")+\"\");");
        method.addBodyLine("return ListResponse.success(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".listCacheMockThenFetchLater(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + "),count,page, limit);");
        return method;
    }

    private Method listWithoutCache(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@CheckLimit");
        method.addAnnotation("@ApiOperation(\"没有缓存查询列表" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/listWithoutCache\")");
        method.setName("listWithoutCache");
        method.setReturnType(listResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(integerType, "page", "@ApiParam(value = \"" + tableName
                + " 页码\") @RequestParam(value = \"page\", required = false, defaultValue = \"1\") "));
        method.addParameter(new Parameter(integerType, "limit", "@ApiParam(value = \"" + tableName
                + " 一页返回条数\") @RequestParam(value = \"limit\", required = false, defaultValue = \"20\")"));
        method.addParameter(new Parameter(stringType, "orderBy", "@ApiParam(value = \"" + tableName
                + " 排序模式\") @RequestParam(value = \"orderBy\", required = false, defaultValue = \"id asc\")"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine(
                modelExampleType.getShortName() + " " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName())
                        + " = new " + modelExampleType.getShortName() + "();");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setLimit(limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOffset((page-1)*limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOrderByClause(orderBy);");
        method.addBodyLine("Integer count = Integer.valueOf(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".countByExampleWithoutCache(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ")+\"\");");
        method.addBodyLine("return ListResponse.success(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".listWithoutCache(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + "),count,page, limit);");
        return method;
    }

    private Method list(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@CheckLimit");
        method.addAnnotation("@ApiOperation(\"有缓存查询列表" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/list\")");
        method.setName("list");
        method.setReturnType(listResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(integerType, "page", "@ApiParam(value = \"" + tableName
                + " 页码\") @RequestParam(value = \"page\", required = false, defaultValue = \"1\") "));
        method.addParameter(new Parameter(integerType, "limit", "@ApiParam(value = \"" + tableName
                + " 一页返回条数\") @RequestParam(value = \"limit\", required = false, defaultValue = \"20\")"));
        method.addParameter(new Parameter(stringType, "orderBy", "@ApiParam(value = \"" + tableName
                + " 排序模式\") @RequestParam(value = \"orderBy\", required = false, defaultValue = \"id asc\")"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine(
                modelExampleType.getShortName() + " " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName())
                        + " = new " + modelExampleType.getShortName() + "();");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setLimit(limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOffset((page-1)*limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOrderByClause(orderBy);");
        method.addBodyLine("Integer count = Integer.valueOf(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".countByExample(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ")+\"\");");
        method.addBodyLine("return ListResponse.success(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".list(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + "),count,page, limit);");
        return method;
    }

    private Method listMockWithoutAuthUser(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@CheckLimit");
        method.addAnnotation("@ApiOperation(\"没有验证token，直接查询缓存列表，返回缓存数据，然后去后台查询进缓存，后面再次查询返回缓存数据" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/listMockWithoutAuthUser\")");
        method.setName("listMockWithoutAuthUser");
        method.setReturnType(listResponse);
        method.addParameter(new Parameter(integerType, "page", "@ApiParam(value = \"" + tableName
                + " 页码\") @RequestParam(value = \"page\", required = false, defaultValue = \"1\") "));
        method.addParameter(new Parameter(integerType, "limit", "@ApiParam(value = \"" + tableName
                + " 一页返回条数\") @RequestParam(value = \"limit\", required = false, defaultValue = \"20\")"));
        method.addParameter(new Parameter(stringType, "orderBy", "@ApiParam(value = \"" + tableName
                + " 排序模式\") @RequestParam(value = \"orderBy\", required = false, defaultValue = \"id asc\")"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine(
                modelExampleType.getShortName() + " " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName())
                        + " = new " + modelExampleType.getShortName() + "();");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setLimit(limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOffset((page-1)*limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOrderByClause(orderBy);");
        method.addBodyLine("Integer count = Integer.valueOf(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".countByExampleCacheMockThenFetchLater(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ")+\"\");");
        method.addBodyLine("return ListResponse.success(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".listCacheMockThenFetchLater(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + "),count,page, limit);");
        return method;
    }

    private Method query(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@CheckLimit");
        method.addAnnotation("@ApiOperation(\"带条件查询列表" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/query\")");
        method.setName("query");
        method.setReturnType(listResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(integerType, "page", "@ApiParam(value = \"" + tableName
                + " 页码\") @RequestParam(value = \"page\", required = false, defaultValue = \"1\") "));
        method.addParameter(new Parameter(integerType, "limit", "@ApiParam(value = \"" + tableName
                + " 一页返回条数\") @RequestParam(value = \"limit\", required = false, defaultValue = \"20\")"));
        method.addParameter(new Parameter(stringType, "orderBy", "@ApiParam(value = \"" + tableName
                + " 排序模式\") @RequestParam(value = \"orderBy\", required = false, defaultValue = \"id asc\")"));
        MybatisUtilCommon.addParameterForColumnsWithMaxMinPrefixSuffixLike(method, introspectedTable);

        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine(
                modelExampleType.getShortName() + " " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName())
                        + " = new " + modelExampleType.getShortName() + "();");
        method.addBodyLine(
                modelExampleType.getShortName() + ".Criteria criteria = " + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".createCriteria();");
        MybatisUtilCommon.addCriteriaForColumnsInMethod(method, introspectedTable);
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setLimit(limit);");
        method.addBodyLine("if(page<1){page=1;}");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOffset((page-1)*limit);");
        method.addBodyLine(MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ".setOrderByClause(orderBy);");
        method.addBodyLine("Integer count = Integer.valueOf(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".countByExample(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + ")+\"\");");
        method.addBodyLine("return ListResponse.success(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(serviceType.getShortName()) + ".list(" + MybatisUtilCommon.toLowerCaseAtFirstCharacter(modelExampleType.getShortName()) + "),count,page, limit);");
        return method;
    }


    protected Method distinct(IntrospectedTable introspectedTable, String tableName) {
        Method method = new Method();
        method.addAnnotation("@AuthUser");
        method.addAnnotation("@ApiOperation(\"查询对应字段的唯一数据列表" + tableName + "\")");
        method.addAnnotation("@GetMapping(value = \"/distinct\")");
        method.setName("distinct");
        method.setReturnType(simpleResponse);
        method.addParameter(new Parameter(stringType, "token", "@ApiParam(value = \"token\")  @RequestHeader(value=\"token\", required = false)"));
        method.addParameter(new Parameter(stringType, "field", "@ApiParam(value = \"查询字段\") @RequestParam(value = \"field\", required = true, defaultValue = \"id\") "));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.addBodyLine("return SimpleResponse.success(" +
                MybatisUtilCommon.toLowerCaseAtFirstCharacter("Distinct"+serviceType.getShortName()) +
                ".getDistinct(field));");
        return method;
    }

}
